﻿using Nop.Core.Domain.Customers;
using Nop.Core.Domain.XJ;
using Nop.Services.Common;
using Nop.Services.Customers;
using Nop.Services.Directory;
using Nop.Services.Logging;
using Nop.Services.Media;
using Nop.Services.Security;
using Nop.Services.XJ;
using Nop.Web.Framework.Security;
using Nop.Web.Models.XJ;
using Senparc.Weixin;
using Senparc.Weixin.Entities.TemplateMessage;
using Senparc.Weixin.MP.Containers;
using Senparc.Weixin.WxOpen.AdvancedAPIs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Mvc;

namespace Nop.Web.Controllers
{
	public class StockInController : Controller
	{
		#region Fields
		private readonly static string appId = "wx254193524213940e";
		private readonly static string appSecret = "c020d4fcaceaef04d03194bcf408ba51";
		private readonly IPermissionService _permissionService;
		private readonly IDepartmentService _departmentService;
		private readonly ICustomerService _customerService;
		private readonly ICustomerActivityService _customerActivityService;
		private readonly IFilesService _filesService;
		private readonly IPictureService _pictureService;
		private readonly IMessageService _messageService;
		private readonly ILogger _logger;
		private readonly IGenericAttributeService _genericAttributeService;
		private readonly IXJPlaceService _xjPlaceService;
		private readonly IXJPlaceSignService _xjPlaceSignService;
		private readonly IXJEquipmentCategoryService _xJEquipmentCategoryService;
		private readonly IXJEquipmentService _xJEquipmentService;
		private readonly IXJEquipmentStockService _xJEquipmentStockService;
		private readonly IXJEquipmentStockInService _xJEquipmentStockInService;
		private readonly IXJEquipmentStockInDetailService _xJEquipmentStockInDetailService;
		private readonly IXJEquipmentStockLogService _xJEquipmentStockLogService;
		private readonly IXJInspectionService _xJInspectionService;
		private readonly IXJInspectionPlanService _xJInspectionPlanService;
		private readonly IXJMaintenanceService _xJMaintenanceService;
		private readonly IXJMaintenanceCommentService _xJMaintenanceCommentService;
		#endregion

		#region Ctor
		public StockInController(
			IPermissionService permissionService,
			IDepartmentService departmentService,
			ICustomerService customerService,
			ICustomerActivityService customerActivityService,
			IFilesService filesService,
			IPictureService pictureService,
			IMessageService messageService,
			ILogger logger,
			IGenericAttributeService genericAttributeService,
			IXJPlaceService xjPlaceService,
			IXJPlaceSignService xjPlaceSignService,
			IXJEquipmentCategoryService xJEquipmentCategoryService,
			IXJEquipmentService xJEquipmentService,
			IXJEquipmentStockService xJEquipmentStockService,
			IXJEquipmentStockInService xJEquipmentStockInService,
			IXJEquipmentStockInDetailService xJEquipmentStockInDetailService,
			IXJEquipmentStockLogService xJEquipmentStockLogService,
			IXJInspectionService xJInspectionService,
			IXJInspectionPlanService xJInspectionPlanService,
			IXJMaintenanceService xJMaintenanceService,
			IXJMaintenanceCommentService xJMaintenanceCommentService)
		{
			this._permissionService = permissionService;
			this._departmentService = departmentService;
			this._customerService = customerService;
			this._customerActivityService = customerActivityService;
			this._filesService = filesService;
			this._pictureService = pictureService;
			this._messageService = messageService;
			this._logger = logger;
			this._genericAttributeService = genericAttributeService;
			this._xjPlaceService = xjPlaceService;
			this._xjPlaceSignService = xjPlaceSignService;
			this._xJEquipmentCategoryService = xJEquipmentCategoryService;
			this._xJEquipmentService = xJEquipmentService;
			this._xJEquipmentStockService = xJEquipmentStockService;
			this._xJEquipmentStockInService = xJEquipmentStockInService;
			this._xJEquipmentStockInDetailService = xJEquipmentStockInDetailService;
			this._xJEquipmentStockLogService = xJEquipmentStockLogService;
			this._xJInspectionService = xJInspectionService;
			this._xJInspectionPlanService = xJInspectionPlanService;
			this._xJMaintenanceService = xJMaintenanceService;
			this._xJMaintenanceCommentService = xJMaintenanceCommentService;
		}
		#endregion

		#region Utilities

		#endregion

		[HttpPost]
		[UserValidator]
		public JsonResult List(Customer customer, string sNo = "", int state = 0, int pageIndex = 0, int pageSize = 10)
		{
			if (null == customer || customer.Deleted)
				return Json(new { result = false, msg = "用户无效" });

			if (customer.IsWarehouseKeeper())
			{
				var ins = _xJEquipmentStockInService.GetAllStockIns(
					sNo: sNo,
					minState: (int)StockInStateEnum.待审核,
					state: state,
					pageIndex: pageIndex,
					pageSize: pageSize);
				return Json(new
				{
					result = true,
					model = ins.Select(x =>
					{
						x.StateName = Enum.GetName(typeof(StockInStateEnum), x.State);
						x.CreatedOnString = x.CreatedOn.ToString("yyyy-MM-dd HH:mm:ss");
						return x;
					}),
					ins.TotalPages
				});
			}
			else if (customer.IsDepartmentManager())
			{
				var ins = _xJEquipmentStockInService.GetAllStockIns(
					sNo: sNo,
					departmentId: customer.DepartmentId,
					minState: (int)StockInStateEnum.待审核,
					state: state,
					pageIndex: pageIndex,
					pageSize: pageSize);
				return Json(new
				{
					result = true,
					model = ins.Select(x =>
					{
						x.StateName = Enum.GetName(typeof(StockInStateEnum), x.State);
						x.CreatedOnString = x.CreatedOn.ToString("yyyy-MM-dd HH:mm:ss");
						return x;
					}),
					ins.TotalPages
				});
			}
			else
			{
				var ins = _xJEquipmentStockInService.GetAllStockIns(
					sNo: sNo,
					customerId: customer.Id,
					state: state,
					pageIndex: pageIndex,
					pageSize: pageSize);
				return Json(new
				{
					result = true,
					model = ins.Select(x =>
					{
						x.StateName = Enum.GetName(typeof(StockInStateEnum), x.State);
						x.CreatedOnString = x.CreatedOn.ToString("yyyy-MM-dd HH:mm:ss");
						return x;
					}),
					ins.TotalPages
				});
			}
		}

		[HttpPost]
		[UserValidator]
		public JsonResult View(Customer customer, int inId)
		{
			if (null == customer || customer.Deleted)
				return Json(new { result = false, msg = "用户无效" });

			var model = new StockInModel();
			var stockIn = _xJEquipmentStockInService.GetXJEquipmentStockInById(inId);
			if (null != stockIn)
			{
				model.Id = stockIn.Id;
				model.SNo = stockIn.SNo;
				model.State = stockIn.State;
				model.StateName = Enum.GetName(typeof(StockOutStateEnum), stockIn.State);
				model.CustomerId = stockIn.CustomerId;
				model.CustomerName = stockIn.CustomerName;
				model.DepartmentId = stockIn.DepartmentId;
				model.DepartmentName = stockIn.DepartmentName;
				model.CreatedOn = stockIn.CreatedOn.ToString("yyyy-MM-dd HH:mm:ss");
				model.Reviewer = stockIn.Reviewer;
				model.ReviewOn = stockIn.ReviewOn.HasValue ? stockIn.ReviewOn.Value.ToString("yyyy-MM-dd HH:mm:ss") : "";
				model.Keeper = stockIn.Keeper;
				model.KeeperOn = stockIn.KeeperOn.HasValue ? stockIn.KeeperOn.Value.ToString("yyyy-MM-dd HH:mm:ss") : "";
				var details = _xJEquipmentStockInDetailService.GetAllStockInDetails(inId);
				if (details.Any())
				{
					foreach (var d in details)
					{
						model.Detail.Add(new StockInDetailModel
						{
							Id = d.Id,
							EquipmentId = d.EquipmentId,
							Title = d.Name,
							Label = string.Format("{0} {1}", d.Manufacturer, d.Specification),
							Amount = d.Amount,
						});
					}
				}
				var pictures = stockIn.GetAttribute<string>("Pictures");
				if (!string.IsNullOrEmpty(pictures))
				{
					var pictureIds = pictures
						.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
						.Select(x => Convert.ToInt32(x))
						.ToArray();
					foreach (var p in pictureIds)
					{
						model.Pictures.Add(_pictureService.GetPictureUrl(p));
					}
				}

				model.NeedAudit = stockIn.State == (int)StockInStateEnum.待审核;
				if (model.NeedAudit)
					model.CanAudit = customer.IsDepartmentManager() && customer.DepartmentId == stockIn.DepartmentId;
				model.NeedIn = stockIn.State == (int)StockInStateEnum.待入库;
				if (model.NeedIn)
					model.CanIn = customer.IsWarehouseKeeper();
			}
			return Json(new { resut = true, model });
		}

		[HttpPost]
		[UserValidator]
		public JsonResult Audit(Customer customer, int inId, bool pass = true)
		{
			if (null == customer || customer.Deleted)
				return Json(new { result = false, msg = "用户无效" });

			var stockIn = _xJEquipmentStockInService.GetXJEquipmentStockInById(inId);
			if (stockIn == null || stockIn.Deleted)
				return Json(new { result = false, msg = "记录无效" });
			if (stockIn.State != (int)StockInStateEnum.待审核)
				return Json(new { result = false, msg = "无需审核" });
			if (!customer.IsAdmin() && !(customer.IsDepartmentManager() && customer.DepartmentId == stockIn.DepartmentId))
				return Json(new { result = false, msg = "不能审核" });

			stockIn.Reviewer = customer.TrueName;
			stockIn.ReviewOn = DateTime.Now;
			stockIn.State = pass ? (int)StockInStateEnum.待入库 : (int)StockInStateEnum.驳回;
			_xJEquipmentStockInService.UpdateXJEquipmentStockIn(stockIn);
			//activity log
			_customerActivityService.InsertActivity("AuditStockIn", "审核入库记录：{0}", inId);
			return Json(new { result = true, msg = "审核成功", id = inId });
		}

		[HttpPost]
		[UserValidator]
		public JsonResult In(Customer customer, int inId, bool pass = true)
		{
			if (null == customer || customer.Deleted)
				return Json(new { result = false, msg = "用户无效" });

			var result = _xJEquipmentStockInService.In(inId, pass, customer);
			if (!result.Result)
			{
				return Json(new { result = false, msg = result.Msg });
			}
			//activity log
			_customerActivityService.InsertActivity("AuditStockIn", "审核入库记录：{0}", inId);
			return Json(new { result = true, msg = "入库成功", id = inId });
		}

		/// <summary>
		/// 提醒部门负责人审核或物资部确认收货
		/// </summary>
		/// <param name="id"></param>
		/// <param name="templateId"></param>
		/// <returns></returns>
		public async Task<JsonResult> SubscribeMessage(int id, string templateId = "nQpdDl04GLhjY7EwrF3rk6orDUEI_WcDQ3lp5FUg09k")
		{
			await AccessTokenContainer.RegisterAsync(appId, appSecret);

			var stockIn = _xJEquipmentStockInService.GetXJEquipmentStockInById(id);
			if (null == stockIn || stockIn.Deleted)
				return Json(new { success = false, msg = "入库记录无效" });

			string thing1 = "";
			string page = string.Format("pages/stockin/detail?id={0}", stockIn.Id);
			var users = new List<Customer>();
			switch (stockIn.State)
			{
				case (int)StockInStateEnum.待审核:
					thing1 = "新的入库申请待审核";
					users = _customerService.GetAllCustomers(
						customerRoleId: _customerService.GetCustomerRoleBySystemName(SystemCustomerRoleNames.DepartmentManager).Id,
						departId: stockIn.DepartmentId
						).ToList();
					break;
				case (int)StockInStateEnum.待入库:
					thing1 = "新的入库申请待入库";
					users = _customerService.GetAllCustomers(
						customerRoleId: _customerService.GetCustomerRoleBySystemName(SystemCustomerRoleNames.WarehouseKeeper).Id
						).ToList();
					break;
				default:
					break;
			}
			if (!users.Any())
				return Json(new { success = false, msg = "无通知用户" });
			try
			{
				var templateMessageData = new TemplateMessageData
				{
					["thing1"] = new TemplateMessageDataValue(thing1),
					["date2"] = new TemplateMessageDataValue(stockIn.CreatedOn.ToString("yyyy年MM月dd日 HH:mm"))
				};

				List<string> openIds = new List<string>();
				string msg = string.Empty;
				bool hasFinished = false;

				foreach (var c in users)
				{
					string openId = c.GetAttribute<string>(SystemCustomerAttributeNames.OpenId);
					if (!string.IsNullOrEmpty(openId))
					{
						openIds.Add(openId);
					}
				}
				foreach (var openId in openIds)
				{
					var result = await MessageApi.SendSubscribeAsync(appId, openId, templateId, templateMessageData, page);
					if (result.errcode == ReturnCode.请求成功)
					{
						hasFinished = true;
					}
					else
					{
						msg = "消息发送失败";
						_logger.Error(result.errmsg);
					}
				}
				if (!hasFinished && !string.IsNullOrEmpty(msg))
					return Json(new { success = false, msg });
				else
				{
					//message.IsFinished = true;
					//_messageService.UpdateMessage(message);
					return Json(new { success = true, msg = "消息已发送" });
				}
			}
			catch (Exception ex)
			{
				_logger.Error(ex.Message);
				return Json(new { success = false, msg = "消息发送失败" });
			}
		}

		/// <summary>
		/// 提醒申请人已入库
		/// </summary>
		/// <param name="id"></param>
		/// <param name="templateId"></param>
		/// <returns></returns>
		public async Task<JsonResult> RemindMessage(int id, string templateId = "nQpdDl04GLhjY7EwrF3rk6orDUEI_WcDQ3lp5FUg09k")
		{
			await AccessTokenContainer.RegisterAsync(appId, appSecret);

			var stockIn = _xJEquipmentStockInService.GetXJEquipmentStockInById(id);
			if (null == stockIn || stockIn.Deleted)
				return Json(new { success = false, msg = "入库记录无效" });

			string thing1 = string.Format("{0}已入库", stockIn.SNo);
			string page = string.Format("pages/stockin/detail?id={0}", stockIn.Id);
			try
			{
				var templateMessageData = new TemplateMessageData
				{
					["thing1"] = new TemplateMessageDataValue(thing1),
					["date2"] = new TemplateMessageDataValue(stockIn.CreatedOn.ToString("yyyy年MM月dd日 HH:mm"))
				};

				List<string> openIds = new List<string>();
				string msg = string.Empty;
				bool hasFinished = false;

				var customer = _customerService.GetCustomerById(stockIn.CustomerId);
				if (null != customer && !customer.Deleted)
				{
					string openId = customer.GetAttribute<string>(SystemCustomerAttributeNames.OpenId);
					if (!string.IsNullOrEmpty(openId))
					{
						openIds.Add(openId);
					}
				}
				foreach (var openId in openIds)
				{
					var result = await MessageApi.SendSubscribeAsync(appId, openId, templateId, templateMessageData, page);
					if (result.errcode == ReturnCode.请求成功)
					{
						hasFinished = true;
					}
					else
					{
						msg = "消息发送失败";
						_logger.Error(result.errmsg);
					}
				}
				if (!hasFinished && !string.IsNullOrEmpty(msg))
					return Json(new { success = false, msg });
				else
				{
					//message.IsFinished = true;
					//_messageService.UpdateMessage(message);
					return Json(new { success = true, msg = "消息已发送" });
				}
			}
			catch (Exception ex)
			{
				_logger.Error(ex.Message);
				return Json(new { success = false, msg = "消息发送失败" });
			}
		}
	}
}